package com.jade.bss.customer.role.impl;

import java.util.Date;
import java.util.List;
import javax.ejb.TransactionAttribute;
import javax.inject.Inject;
import javax.inject.Named;

import com.jade.bss.customer.CustomerConstants;
import com.jade.bss.customer.CustomerException;
import com.jade.bss.customer.grant.GrantManager;
import com.jade.bss.customer.principal.PrincipalFactory;
import com.jade.bss.customer.principal.SimplePrincipal;
import com.jade.bss.customer.role.RoleDao;
import com.jade.bss.customer.role.RoleEntry;
import com.jade.bss.customer.role.RoleManager;
import com.jade.framework.base.criterion.Criteria;
import com.jade.framework.base.util.PagingList;
import org.springframework.transaction.annotation.Transactional;

/**
 * RoleManager实现，采用RoleDao进行数据访问。
 *
 * @author sky
 * @version 1.0 13-4-18 上午10:12
 */
@Named ("bss_roleManager")
public class RoleManagerImpl implements RoleManager
{
    protected RoleDao roleDao;
    protected PrincipalFactory principalFactory;

    protected GrantManager grantManager;

    public GrantManager getGrantManager()
    {
        return grantManager;
    }

    @Inject
    public void setGrantManager(@Named ("bss_grantManager") GrantManager grantManager)
    {
        this.grantManager = grantManager;
    }

    @Inject
    public void setRoleDao(@Named ("bss_roleDao") RoleDao roleDao)
    {
        this.roleDao = roleDao;
    }

    @Inject
    public void setPrincipalFactory(@Named ("bss_principalFactory") PrincipalFactory principalFactory)
    {
        this.principalFactory = principalFactory;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public int addRole(RoleEntry role)
            throws CustomerException
    {
        if (roleExists(role.getName())) {
            throw new CustomerException(CustomerConstants.ERR_ROLE_EXISTED, role.getName());
        }
        role.setCreationDate(new Date());
        return roleDao.addRole(role);
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public void removeRoles(int[] ids)
            throws CustomerException
    {
        for (int id : ids) {
            removeRole(id);
        }
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public void removeRole(int id)
            throws CustomerException
    {
        RoleEntry role = getRole(id);
        if (role == null) {
            throw new CustomerException(CustomerConstants.ERR_ROLE_NOT_EXISTED, null, id);
        }
        grantManager.revokePrincipals(id);

        SimplePrincipal principal = new SimplePrincipal();
        principal.setName(String.valueOf(role.getId()));
        principal.setType(SimplePrincipal.TYPE_ROLE);
        grantManager.revokePermissions(principal);

        roleDao.removeRole(role);
    }

    public boolean roleExists(String roleName)
            throws CustomerException
    {
        RoleEntry role = getRole(roleName);
        return role != null;
    }

    @TransactionAttribute
    @Transactional (rollbackFor = Exception.class)
    public void updateRole(RoleEntry role)
            throws CustomerException
    {
        RoleEntry oldRole = getRole(role.getId());
        if (oldRole == null) {
            throw new CustomerException(CustomerConstants.ERR_ROLE_NOT_EXISTED, null, role.getId());
        }

        oldRole = getRole(role.getName());
        if (oldRole != null && oldRole.getId() != role.getId()) {
            throw new CustomerException(CustomerConstants.ERR_ROLE_EXISTED, null, role.getName());
        }

        roleDao.updateRole(role);
    }

    public RoleEntry getRole(String name)
    {
        return roleDao.getRole(name);
    }

    public RoleEntry getRole(int id)
    {
        return roleDao.getRole(id);
    }

    public List<RoleEntry> listRole()
            throws CustomerException
    {
        return roleDao.listRole();
    }

    public List<RoleEntry> listRole(String type)
            throws CustomerException
    {
        return roleDao.listRole(type);
    }

    public PagingList<RoleEntry> queryRole(Criteria criteria)
    {
        return roleDao.queryRole(criteria);
    }

    @TransactionAttribute
    public void updateStatus(int id, int status)
            throws CustomerException
    {
        roleDao.updateStatus(id, status);
    }

    //    public List<RoleEntry> listRole(Principal principal)
    //            throws AdminException
    //    {
    //        String principalType = principalFactory.getPrincipalType(principal);
    //        List<PrincipalRole> list = roleDao.listPrincipalRole(principalType, principal.getName());
    //        List<RoleEntry> roleList = new ArrayList<RoleEntry>();
    //        for (PrincipalRole pr : list) {
    //            roleList.add(pr.getRole());
    //        }
    //        return roleList;
    //    }
    //
    //    public List<Principal> listPrincipal(int roleId)
    //    {
    //        List<PrincipalRole> list = roleDao.listPrincipalRole(roleId);
    //        List<Principal> principalList = new ArrayList<Principal>();
    //        for (PrincipalRole pr : list) {
    //            Principal principal = principalFactory.createPrincipal(pr.getPrincipalType(), pr.getPrincipalName());
    //            principalList.add(principal);
    //        }
    //        return principalList;
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void addRoleToPrincipal(Principal principal, int roleId)
    //            throws AdminException
    //    {
    //        //get role
    //        RoleEntry role = getRole(roleId);
    //        if (role == null) {
    //            throw new AdminException(AdminConstants.ERR_ROLE_NOT_EXISTED, null, roleId);
    //        }
    //        String principalType = principalFactory.getPrincipalType(principal);
    //        // check if the principal has already contained the role
    //        PrincipalRole pr = roleDao.getPrincipalRole(principalType, principal.getName(), roleId);
    //        if (pr != null) {
    //            throw new AdminException(AdminConstants.ERR_ROLE_PRINCIPAL_EXISTED, null, principalType,
    //                                     principal.getName(), roleId);
    //        }
    //        pr = new PrincipalRole();
    //        pr.setPrincipalType(principalType);
    //        pr.setPrincipalName(principal.getName());
    //        pr.setRole(role);
    //        roleDao.addPrincipalRole(pr);
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void setRoleToPrincipal(Principal principal, int[] roleIds)
    //            throws AdminException
    //    {
    //        removeRoleFromPrincipal(principal);
    //        addRoleToPrincipal(principal, roleIds);
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void addRoleToPrincipal(Principal principal, int[] roleIds)
    //            throws AdminException
    //    {
    //        for (int roleId : roleIds) {
    //            addRoleToPrincipal(principal, roleId);
    //        }
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void removeRoleFromPrincipal(Principal principal, int roleId)
    //            throws AdminException
    //    {
    //        String principalType = principalFactory.getPrincipalType(principal);
    //        roleDao.removePrincipalRole(principalType, principal.getName(), roleId);
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void removeRoleFromPrincipal(Principal principal, int[] roleIds)
    //            throws AdminException
    //    {
    //        for (int roleId : roleIds) {
    //            removeRoleFromPrincipal(principal, roleId);
    //        }
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void removeRoleFromPrincipal(Principal principal)
    //            throws AdminException
    //    {
    //        String principalType = principalFactory.getPrincipalType(principal);
    //        roleDao.removePrincipalRole(principalType, principal.getName());
    //    }
    //
    //    @TransactionAttribute
    //    @Transactional (rollbackFor = Exception.class)
    //    public void removePrincipalFromRole(int roleId)
    //            throws AdminException
    //    {
    //        roleDao.removePrincipalRole(roleId);
    //    }
}
